/*
 * WorkQueue.cpp
 *
 *	Author: stravant
 *	Description:
 *		
 */

#include "WorkQueue.h"

namespace tbt {

template <class T>
WorkQueue<T>::WorkQueue(): mReadQueueHead(nullptr), mWriteQueueHead(nullptr),
							mReadQueueTail(nullptr), mWriteQueueTail(nullptr) {
}

template <class T>
WorkQueue<T>::~WorkQueue() {
	delete mReadQueueHead;
	delete mWriteQueueHead;
}

template <class T>
void WorkQueue<T>::push(T a) {
	mWriteLock.lock();
	auto newNode = new typename WorkQueue<T>::ListNode(a);
	if (mWriteQueueTail) {
		mWriteQueueTail->Next = newNode;
	} else {
		mWriteQueueHead = newNode;
	}
	mWriteQueueTail = newNode;
	mWriteLock.unlock();
}

template <class T>
T WorkQueue<T>::pop() {
	if (mReadQueueHead) {
		//pop the readlisthead

		//this is the only node, zero out the tail
		if (mReadQueueHead == mReadQueueTail) {
			mReadQueueTail = nullptr;
		}

		//save the node
		auto node = mReadQueueHead;

		//advance to next
		mReadQueueHead = mReadQueueHead->Next;

		//save the result
		auto val = node->Value;

		//delete the node
		delete node;

		//return the value
		return val;
	} else {
		unreachable;
	}
}

template <class T>
bool WorkQueue<T>::swap() {
	mWriteLock.lock();
	if (mWriteQueueHead) {
		//append the write list to the read list
		if (mReadQueueTail) {
			mReadQueueTail->Next = mWriteQueueHead;
			mReadQueueTail = mWriteQueueTail;
		} else {
			mReadQueueTail = mWriteQueueTail;
			mReadQueueHead = mWriteQueueHead;
		}
		mWriteQueueHead = mWriteQueueTail = 0;
	}
	mWriteLock.unlock();

	return mReadQueueHead != nullptr;
}

template <class T>
bool WorkQueue<T>::empty() const {
	return mReadQueueHead == nullptr;
}

template <class T>
T& WorkQueue<T>::next() const {
	assert(mReadQueueHead != nullptr);
	return mReadQueueHead->Value;
}

}













